package com.cardone.platform.authority.service;

import com.cardone.common.util.MapperUtils;
import com.cardone.context.Attributes;
import com.cardone.context.ContextHolder;
import com.cardone.platform.authority.dao.PermissionDao;
import com.cardone.platform.authority.dao.RolePermissionDao;
import com.cardone.platform.authority.dto.PermissionDto;
import com.cardone.platform.configuration.service.DictionaryService;
import com.cardone.platform.configuration.service.SiteService;
import com.cardone.platform.usercenter.util.UserUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.reflect.TypeToken;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;

/**
 * 许可服务
 *
 * @author yaohaitao
 */
@Getter
@Setter
@Transactional(readOnly = true)
public class PermissionDefaultService extends com.cardone.common.service.SimpleDefaultService<com.cardone.platform.authority.dto.PermissionDto> implements PermissionService {
    @Override
    public PermissionDao getDao() {
        return ContextHolder.getBean(PermissionDao.class);
    }

    @Override
    public List<PermissionDto> toList(String json) {
        return MapperUtils.fromJson(new TypeToken<List<PermissionDto>>() {
        }.getType(), json);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void initList(List<PermissionDto> dList) {
        int orderNum = 1;

        for (PermissionDto d : dList) {
            if (StringUtils.isBlank(d.getSiteId())) {
                Map<String, Object> findSiteMap = Maps.newHashMap();

                findSiteMap.put(Attributes.projectCode.name(), d.getProjectCode());
                findSiteMap.put(Attributes.code.name(), d.getSiteCode());

                final String siteId = ContextHolder.getBean(SiteService.class).readByCode(String.class, Attributes.id.name(), findSiteMap);

                if (StringUtils.isBlank(siteId)) {
                    continue;
                }

                d.setSiteId(siteId);
            }

            if (StringUtils.isBlank(d.getTypeId())) {
                final String typeId = ContextHolder.getBean(DictionaryService.class).readIdByTypeCodeAndCode(d.getTypeTypeCode(), d.getTypeCode());

                if (StringUtils.isBlank(typeId)) {
                    continue;
                }

                d.setTypeId(typeId);
            }

            if (d.getOrderNum() == null) {
                d.setOrderNum(new Long(10 * orderNum++));
            }

            PermissionDto oldD = this.saveByIdOrCode(PermissionDto.class, d);

            List<PermissionDto> permissionChilds = d.getChilds();

            if (CollectionUtils.isEmpty(permissionChilds)) {
                continue;
            }

            for (final PermissionDto permissionChild : permissionChilds) {
                if (StringUtils.isBlank(permissionChild.getSiteCode())) {
                    permissionChild.setSiteId(d.getSiteId());
                }

                if (StringUtils.isBlank(permissionChild.getTypeCode())) {
                    permissionChild.setTypeId(d.getTypeId());
                }

                permissionChild.setParentId(oldD.getId());
            }

            this.initList(permissionChilds);
        }
    }

    @Override
    @Transactional(readOnly = true)
    public <P> List<P> findListBySiteId(final Class<P> mappedClass, final String siteId) {
        return ContextHolder.getBean(PermissionDao.class).findListBySiteId(mappedClass, siteId);
    }

    @Override
    @Transactional(readOnly = true)
    public <P> List<P> findListBySiteIdAndRoleId(final Class<P> mappedClass, final String siteId, final String roleId) {
        return ContextHolder.getBean(PermissionService.class).findListBySiteIdAndRoleIdList(mappedClass, siteId, Lists.newArrayList(roleId));
    }

    @Override
    @Transactional(readOnly = true)
    public <P> List<P> findListBySiteIdAndTypeId(final Class<P> mappedClass, final String siteId, final String typeId) {
        return ContextHolder.getBean(PermissionDao.class).findListBySiteIdAndTypeId(mappedClass, siteId, typeId);
    }

    @Override
    @Transactional(readOnly = true)
    public <P> List<P> findListBySiteIdAndTypeCode(final Class<P> mappedClass, final String siteId, final String typeCode) {
        return ContextHolder.getBean(PermissionDao.class).findListBySiteIdAndTypeCode(mappedClass, siteId, typeCode);
    }

    @Override
    @Transactional(readOnly = true)
    public List<String> readCodeListBySiteIdAndTypeCode(final String siteId, final String typeCode) {
        return ContextHolder.getBean(PermissionDao.class).readCodeListBySiteIdAndTypeCode(siteId, typeCode);
    }

    @Override
    @Transactional(readOnly = true)
    public <P> List<P> findListBySiteIdAndRoleIdList(final Class<P> mappedClass, final String siteId, final List<String> roleIdList) {
        return ContextHolder.getBean(PermissionDao.class).findListBySiteIdAndRoleIdList(mappedClass, siteId, roleIdList);
    }

    @Override
    public List<PermissionDto> findListForRoleId(String roleId, String isRemove) {
        String siteId = UserUtils.find().getSiteId();

        List<String> permissionCodeList = ContextHolder.getBean(RolePermissionDao.class).readListPermissionCodeBySiteIdAndRoleId(siteId, roleId);

        if (BooleanUtils.toBoolean(isRemove) && org.apache.commons.collections.CollectionUtils.isEmpty(permissionCodeList)) {
            return Lists.newArrayList();
        }

        List<PermissionDto> permissionList = ContextHolder.getBean(PermissionDao.class).findListBySiteIdAndTypeId(PermissionDto.class, siteId, null);

        if (org.apache.commons.collections.CollectionUtils.isEmpty(permissionList) || org.apache.commons.collections.CollectionUtils.isEmpty(permissionCodeList)) {
            return permissionList;
        }

        for (int i = permissionList.size() - 1; i >= 0; i--) {
            final PermissionDto permission = permissionList.get(i);

            permission.setName(permission.getTypeName() + "->" + permission.getName());

            boolean isMatch = com.cardone.common.util.StringUtils.matchList(permissionCodeList, permission.getCode());

            if (isMatch) {
                permission.setChecked(true);

                continue;
            }

            if (BooleanUtils.toBoolean(isRemove)) {
                permissionList.remove(i);
            }
        }

        return permissionList;
    }
}
